package com.yuyue.springFramework.note04;

import com.yuyue.springFramework.note04.annotation.*;
import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

/**
 * 《Spring-4 Java的注解.md》文章代码
 *  文章地址：https://mp.weixin.qq.com/s/M4XM7f3U01_SHoMOiYwN5A
 */
public class Note04Test {
    @Test
    //注解使用 @interface 定义
    @MyAnnotation
    public void fun1(){}

    @Test
    //一个参数的注解
    @Annotation2(name = "一个参数，参数名称不为value，需填写参数名")
    public void fun2(){}

    @Test
    //一个参数的注解
    @Annotation3("一个名为 value 的参数，可以省略参数名")
    public void fun3(){}

    @Test
    //参数为数组类型的注解，调用时需以 {} 包起来，以 , 分隔
    @Annotation4("数组类型仅有一个值时，不需要使用 {}")
    public void fun4(){
        @Annotation4({"参数1", "2"})
        String i;
    }

    @Test
    //存在默认值时，使用注解可以不用赋值，没有默认值则必须赋值
    @Annotation5(name = "仅为没有默认值的赋值")
    public void fun5(){ }

    @Test
    //解析类上的注解
    public void fun6(){
        for (Annotation annotation:
             TargetObject.class.getAnnotations()) {
            System.out.println(annotation);
        }
    }

    @Test
    //解析类的变量类型注解
    public void fun7(){
        TypeVariable<Class<TargetObject>>[] typeVariables = TargetObject.class.getTypeParameters();
        for (TypeVariable<Class<TargetObject>> typeVariable:
                typeVariables) {
            System.out.println(typeVariable.getName() + "变量类型注解信息：");

            Annotation[] annotations = typeVariable.getAnnotations();
            for (Annotation annotation:
                 annotations) {

                System.out.println(annotation);
            }
        }
    }

    @Test
    //解析成员变量name的注解
    public void fun8() throws NoSuchFieldException {
        Field field = TargetObject.class.getDeclaredField("name");
        for (Annotation annotation:
                field.getAnnotations()) {
            System.out.println(annotation);
        }
    }

    @Test
    //解析成员变量map的泛型的注解
    public void fun9() throws NoSuchFieldException {
        Field field = TargetObject.class.getDeclaredField("map");
        Type genericType = field.getGenericType();
        Type[] actualTypeArguments = ((ParameterizedType)genericType).getActualTypeArguments();

        AnnotatedType annotatedType = field.getAnnotatedType();
        AnnotatedType[] annotatedActualTypeArguments = ((AnnotatedParameterizedType)annotatedType).getAnnotatedActualTypeArguments();

        for (int i=0; i < annotatedActualTypeArguments.length; i++){
            Type actualTypeArguments1 = actualTypeArguments[i];
            System.out.println(actualTypeArguments1.getTypeName() + "类型上的注解如下：");

            AnnotatedType actualTypeArgument = annotatedActualTypeArguments[i];
            for (Annotation annotation:
                 actualTypeArgument.getAnnotations()) {
                System.out.println(annotation);
            }
        }
    }

    @Test
    //构造器上的注解
    public void fun10() throws NoSuchMethodException {
        Constructor constructor = TargetObject.class.getConstructor();

        for (Annotation a:
             constructor.getAnnotations()) {
            System.out.println(a);
        }
    }

    @Test
    //成员方法上的注解
    public void fun11() throws NoSuchMethodException {
        Method method = TargetObject.class.getMethod("fun", String.class);

        for (Annotation a:
                method.getAnnotations()) {
            System.out.println(a);
        }
    }

    @Test
    //成员方法参数上的注解
    public void fun12() throws NoSuchMethodException {
        Method method = TargetObject.class.getMethod("fun", String.class);

        for (Parameter parameter:
             method.getParameters()) {
            //System.out.println(parameter.getName() + "参数的注解如下");
            System.out.println(String.format("参数%s上的注解如下:", parameter.getName()));

            for (Annotation annotation:
                    parameter.getAnnotations()) {
                System.out.println(annotation);
            }
        }
    }

    @Test
    //验证注解的基础
    public void fun13(){
        InheritAnnotation inheritAnnotation = new InheritAnnotation();
        inheritAnnotation.fun();
    }

}
